#!/usr/bin/env python
#
# Copyright 2011 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""CollectionHandler issues JSON representations of collection trees."""

__author__ = 'Vic Fryzel <vicfryzel@google.com>'

import atom
import json
import gdata.client
from google.appengine.ext import webapp
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.ext.webapp.util import run_wsgi_app
from gcategorically.oauth_handler import OAuthTokenHandler


class RootCollection(object):
  """Generic representation of folder:root from API.

  This is needed because there is no physical root folder object given back
  by the API.
  """
  title = "Home"
  resource_id = 'folder:root'

  def GetSelfLink(self):
    """Emulate the GetSelfLink of a GData Entry object."""
    link = atom.data.Link()
    # Link is given in the API documentation.
    link.href = "https://docs.google.com/feeds/default/private/full/folder%3Aroot"
    return link


class CollectionHandler(blobstore_handlers.BlobstoreUploadHandler):
  def GenerateCollectionsTree(self, collections, parent=None):
    add_all_with_no_parents = False
    if parent is None:
      parent = RootCollection()
      add_all_with_no_parents = True

    if not hasattr(parent, 'subCollections'):
      parent.subCollections = []

    if add_all_with_no_parents:
      parent.subCollections.extend(
          filter(lambda x: len(x.InCollections()) == 0, collections))

    for child in collections:
      if parent.GetSelfLink().href in map(lambda x: x.href, child.InCollections()):
        parent.subCollections.append(
            self.GenerateCollectionsTree(collections, parent=child))
    return parent

  def CollectionsTreeToSerializable(self, parent):
    retval = {}
    if hasattr(parent.title, 'text'):
      retval['title'] = parent.title.text
    else:
      retval['title'] = parent.title

    if hasattr(parent.resource_id, 'text'):
      retval['resource_id'] = parent.resource_id.text
    else:
      retval['resource_id'] = parent.resource_id

    if hasattr(parent.GetSelfLink(), 'href'):
      retval['link'] = parent.GetSelfLink().href
    else:
      retval['link'] = parent.GetSelfLink()

    retval['subCollections'] = []
    if hasattr(parent, 'subCollections'):
      for collection in parent.subCollections:
        retval['subCollections'].append(
            self.CollectionsTreeToSerializable(collection))
    return retval

  def get(self):
    """Return the user interface."""
    th = OAuthTokenHandler()
    client = th.GetAuthorizedClient()
    if client is None:
      self.redirect('/auth')
      return

    collections = client.GetResources(
        '/feeds/default/private/full/-/folder?showroot=true').entry
    collections_tree = self.GenerateCollectionsTree(collections)
    collections_tree_json = json.dumps(self.CollectionsTreeToSerializable(
        collections_tree))
    self.response.headers['Content-Type'] = 'text/json'
    self.response.out.write(collections_tree_json)

  def post(self):
    """Send given uploaded files to the Documents List API."""
    th = OAuthTokenHandler()
    client = th.GetAuthorizedClient()
    parent = self.request.get('parent')

    uri = ('/feeds/upload/create-session/default/private/full/%s/contents'
           '?convert=false' % parent)

    files = self.get_uploads()
    for blob_info in files:
      if client is None:
        blob_info.delete()
        self.redirect('/auth')
        return

      uploader = gdata.client.ResumableUploader(
          client, blob_info.open(), blob_info.content_type, blob_info.size,
          desired_class=gdata.docs.data.Resource,
          chunk_size=524288)
      entry = gdata.docs.data.Resource(title=atom.data.Title(
          text=blob_info.filename))
      uploader.UploadFile(uri, entry=entry)

      blob_info.delete()
    self.redirect('/')


# The application container that runs a DefaultHandler and maps it to the / URI.
application = webapp.WSGIApplication(
    [('/collections.json', CollectionHandler)], debug=True)


def main():
  """Run the DefaultHandler application."""
  run_wsgi_app(application)


if __name__ == "__main__":
  main()
